﻿using System;
using System.Collections.Generic;

using System.Text;
using Efficient.DataAccess;
using Common.Logging;

namespace Efficient.Domain
{
    public class KeywordTable : ValueType<KeywordTable>
    {
        private static readonly ILog logger = LogManager.GetLogger(typeof(KeywordTable));
        private string name;
        private readonly IList<KeywordField> fields = new List<KeywordField>();
        private const string keywordPlaceHolder = "$keyword__";
        private const string fieldPrixPlaceHolder = "$pfix__$";
        private const string keywordPrix = "__keyword__";
        private IDbService dao;

        internal IDbService Dao
        {
            set { dao = value; }
        }

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        public IList<KeywordField> Fields
        {
            get { return fields; }
        }

        public KeywordTable(string name)
        {
            this.name = name;
        }

        public KeywordTable()
            : this(string.Empty)
        {
        }

        public void AddField(string name, KeyMode mode)
        {
            KeywordField field = new KeywordField(this, name, mode);
            if (!this.fields.Contains(field))
            {
                this.fields.Add(field);
            }
        }

        public void AddField(string name)
        {
            AddField(name);
        }

        private string BuildQueryAllPart(string fieldPrix)
        {
            StringBuilder query = new StringBuilder("select ");
            query.AppendFormat("{0}* from {1}{2}{3} ", fieldPrixPlaceHolder, dao.OpenQuote, name, dao.CloseQuote);
            query.Replace(fieldPrixPlaceHolder, string.IsNullOrEmpty(fieldPrix) ? string.Empty : string.Concat(fieldPrix, "."));
            return query.ToString();
        }

        public string BuildQueryAll(params OrderField[] orderFields)
        {
            return BuildQueryAll(string.Empty, orderFields);
        }

        public string BuildQueryAll(string fieldPrix, params OrderField[] orderFields)
        {
            StringBuilder query = new StringBuilder("select ");
            query.AppendFormat("{0}* from {1}{2}{3} ", fieldPrixPlaceHolder, dao.OpenQuote, name, dao.CloseQuote);
            if (orderFields != null && orderFields.Length > 0)
            {
                query.Append(" order by ");
                for (int i = 0; i < orderFields.Length; i++)
                {
                    query.AppendFormat("{0}{1}{2}{3} {4}", fieldPrixPlaceHolder,dao.OpenQuote, orderFields[i].PropertyName,dao.CloseQuote, orderFields[i].Ascending ? "asc" : "desc");
                    if (i < orderFields.Length - 1)
                    {
                        query.Append(", ");
                    }
                }
            }
            query.Replace(fieldPrixPlaceHolder, string.IsNullOrEmpty(fieldPrix) ? string.Empty : string.Concat(fieldPrix, "."));

            return query.ToString();
        }

        public KeywordQuery BuildQueryByKeyword(params OrderField[] orderFields)
        {
            return BuildQueryByKeyword(string.Empty, orderFields);
        }

        public KeywordQuery BuildQueryByKeyword(string fieldPrix, params OrderField[] orderFields)
        {
            StringBuilder query = new StringBuilder(BuildQueryAllPart(fieldPrix));
            KeywordQuery where = BuildKeywordQueryPart(fieldPrix);
            if (!string.IsNullOrEmpty(where.QueryString))
            {
                query.AppendFormat("where {0}", where.QueryString);
            }
            if (orderFields != null && orderFields.Length > 0)
            {
                query.Append(" order by ");
                for (int i = 0; i < orderFields.Length; i++)
                {
                    query.AppendFormat(" {0}{1} ", fieldPrixPlaceHolder, orderFields[i]);
                    if (i < orderFields.Length - 1)
                    {
                        query.Append(", ");
                    }
                }
                query.Replace(fieldPrixPlaceHolder, string.IsNullOrEmpty(fieldPrix) ? string.Empty : string.Concat(fieldPrix, "."));
            }
            where.QueryString = query.ToString();
            return where;
        }

        public KeywordQuery BuildKeywordQueryPart()
        {
            return BuildKeywordQueryPart(string.Empty);
        }

        public KeywordQuery BuildKeywordQueryPart(string fieldPrix)
        {
            StringBuilder filter = new StringBuilder();
            KeywordQuery result = new KeywordQuery();
            int count = this.fields.Count;
            for (int i = 0; i < count; i++)
            {
                KeywordField field = this.fields[i];
                filter.AppendFormat("{0}{1}{2}{3} like {4}{2}__ ", fieldPrixPlaceHolder, dao.OpenQuote, field.Field, dao.CloseQuote, keywordPlaceHolder);
                Keyword keyword = new Keyword(string.Concat(dao.ParamNamedPrefix, keywordPrix, field.Field, "__"), field.MatchMode);
                if (!result.KeywordSet.Contains(keyword))
                {
                    result.KeywordSet.Add(keyword);
                }

                if (i < count - 1)
                {
                    filter.Append("or ");
                }
            }
            if (filter.Length > 0)
            {
                if (logger.IsDebugEnabled)
                {
                    logger.Debug("关键字查询条件(解析前):" + filter.ToString());
                }
                filter.Insert(0, "(");
                filter.Append(")");
                filter.Replace(keywordPlaceHolder, string.Concat(dao.ParamNamedPrefix,keywordPrix));
                filter.Replace(fieldPrixPlaceHolder, string.IsNullOrEmpty(fieldPrix) ? string.Empty : string.Concat(fieldPrix, "."));
            }

            result.QueryString = filter.ToString();
            if (logger.IsDebugEnabled)
            {
                logger.Debug("关键字查询条件(解析后):" + result.QueryString);
            }
            return result;
        }

        

        public override int GetHashCode()
        {
            return this.name.GetHashCode() + fields.GetHashCode();
        }

        protected override bool BusinessEquals(KeywordTable entity)
        {
            return entity.name.Equals(this.name, StringComparison.OrdinalIgnoreCase) &&
                entity.fields.Equals(this.fields);
        }

        public override int CompareTo(KeywordTable other)
        {
            return 0;
        }
    }
}
